package com.kxmall.common.core.controller;

import com.kxmall.common.core.domain.R;
import com.kxmall.common.core.domain.model.LoginUser;
import com.kxmall.common.enums.DeviceType;
import com.kxmall.common.exception.ServiceException;
import com.kxmall.common.helper.LoginHelper;
import com.kxmall.common.utils.StringUtils;

/**
 * web层App通用数据处理
 *
 * @author kxmall
 */
public class BaseRiderController {

    /**
     * 响应返回结果
     *
     * @param rows 影响行数
     * @return 操作结果
     */
    protected R<Void> toAjax(int rows) {
        return rows > 0 ? R.ok() : R.fail();
    }

    /**
     * 响应返回结果
     *
     * @param result 结果
     * @return 操作结果
     */
    protected R<Void> toAjax(boolean result) {
        return result ? R.ok() : R.fail();
    }

    /**
     * 页面跳转
     */
    public String redirect(String url) {
        return StringUtils.format("redirect:{}", url);
    }

    /**
     * 获取用户缓存信息
     */
    public LoginUser getLoginUser() {
        return LoginHelper.getLoginUser();
    }

    /**
     * 获取骑手用户缓存信息（安全版本 + Token隔离验证）
     * 防止ThreadLocal污染导致的用户信息串号，确保Token隔离
     */
    public LoginUser getRiderLoginUser() {
        // 1. 验证Token是否存在
        if (!cn.dev33.satoken.stp.StpUtil.isLogin()) {
            throw new ServiceException("骑手未登录");
        }

        // 2. 验证设备类型隔离
        DeviceType deviceType = LoginHelper.getDeviceType();
        if (!DeviceType.RIDER.equals(deviceType)) {
            throw new ServiceException("设备类型不正确，期望: RIDER, 实际: " + deviceType + " - 可能存在Token隔离问题");
        }

        // 3. 强制从Token获取用户信息，跳过ThreadLocal缓存（防止串号）
        LoginUser loginUser = LoginHelper.getLoginUserFromToken();

        // 4. 验证用户类型隔离
        if (!"rider_user".equals(loginUser.getUserType())) {
            throw new ServiceException("用户类型不匹配，期望: rider_user, 实际: " + loginUser.getUserType() + " - 可能存在Token隔离问题");
        }

        // 5. 双重验证LoginId格式（关键的隔离验证）
        String expectedLoginId = "rider_user:" + loginUser.getUserId();
        String actualLoginId = cn.dev33.satoken.stp.StpUtil.getLoginIdAsString();
        if (!expectedLoginId.equals(actualLoginId)) {
            throw new ServiceException("骑手身份验证失败，请重新登录 - 期望: " + expectedLoginId + ", 实际: " + actualLoginId + " - Token隔离验证失败");
        }

        // 6. 验证Token和用户ID的一致性
        Long tokenUserId = LoginHelper.getUserId();
        if (!loginUser.getUserId().equals(tokenUserId)) {
            throw new ServiceException("骑手身份验证失败，数据不一致 - LoginUser: " + loginUser.getUserId() + ", Token: " + tokenUserId);
        }

        // 7. 验证Token隔离完整性（新增）
        validateRiderTokenIsolation(loginUser, deviceType);

        // 8. 记录Token隔离监控信息
        recordRiderTokenIsolationInfo(loginUser);

        // 9. 记录Token使用监控（新增）
        recordRiderTokenUsage("骑手用户获取");

        return loginUser;
    }

    /**
     * 验证骑手Token隔离完整性
     */
    private void validateRiderTokenIsolation(LoginUser loginUser, DeviceType deviceType) {
        try {
            // 验证Token前缀和设备绑定
            String tokenValue = cn.dev33.satoken.stp.StpUtil.getTokenValue();
            String loginDevice = cn.dev33.satoken.stp.StpUtil.getLoginDevice();

            // 确保Token与设备类型绑定正确
            if (!DeviceType.RIDER.getDevice().equals(loginDevice)) {
                throw new ServiceException("Token设备绑定验证失败 - 期望: " + DeviceType.RIDER.getDevice() + ", 实际: " + loginDevice);
            }

            // 记录Token隔离验证成功日志
            System.out.println(String.format(
                "✅ 骑手Token隔离验证通过 - 骑手ID: %s, 设备: %s, Token前缀: %s",
                loginUser.getUserId(),
                loginDevice,
                tokenValue != null ? tokenValue.substring(0, Math.min(10, tokenValue.length())) + "..." : "null"
            ));

        } catch (Exception e) {
            System.err.println(String.format(
                "🚨 骑手Token隔离验证失败 - 骑手ID: %s, 错误: %s",
                loginUser.getUserId(), e.getMessage()
            ));
            throw new ServiceException("Token隔离验证失败: " + e.getMessage());
        }
    }

    /**
     * 记录骑手Token隔离监控信息
     */
    private void recordRiderTokenIsolationInfo(LoginUser loginUser) {
        try {
            // 记录Token隔离状态
            System.out.println(String.format(
                "🔒 骑手Token隔离验证通过 - 骑手ID: %s, 用户类型: %s, 设备类型: %s, LoginId: %s",
                loginUser.getUserId(),
                loginUser.getUserType(),
                DeviceType.RIDER.getDevice(),
                cn.dev33.satoken.stp.StpUtil.getLoginIdAsString()
            ));

        } catch (Exception e) {
            System.err.println("记录骑手Token隔离监控信息异常: " + e.getMessage());
        }
    }

    /**
     * 记录骑手Token使用监控
     */
    private void recordRiderTokenUsage(String operation) {
        try {
            String tokenValue = cn.dev33.satoken.stp.StpUtil.getTokenValue();
            if (tokenValue != null) {
                System.out.println(String.format(
                    "📊 骑手Token使用监控 - 操作: %s, Token前缀: %s",
                    operation, tokenValue.substring(0, Math.min(10, tokenValue.length())) + "..."
                ));
            }
        } catch (Exception e) {
            System.err.println("记录骑手Token使用监控异常: " + e.getMessage());
        }
    }



    /**
     * 获取登录用户id
     */
    public Long getUserId() {
        return LoginHelper.getUserId();
    }

    /**
     * 获取登录用户名
     */
    public String getUsername() {
        return LoginHelper.getUsername();
    }
}
